package com.emisky.pictures.common;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.alibaba.druid.util.IOUtils;
import com.emisky.pictures.common.exception.PictureException;
import com.emisky.pictures.entity.PictureEntity;
import com.emisky.pictures.entity.PicturePathEntity;
import com.emisky.pictures.entity.PictureSizeEntity;
import com.emisky.pictures.entity.WaterMarkEntity;

public class PictureHelper {
	/**
	 * 根据站点key获取水印信息
	 * @param siteKey
	 * @return
	 */
	public WaterMarkEntity getWaterMark(String siteKey){
		return QueryHelper.queryBean(WaterMarkEntity.class, 
				"select wmid,sitekey,location,watermarkpath,opacity from watermark where sitekey=? limit 1",
				siteKey);
	}
	
	/**
	 * 根据sitekey 获取图片路径信息
	 * @param siteKey
	 * @return
	 */
	public List<PicturePathEntity> getPicturePaths(String siteKey){
		return QueryHelper.queryList(PicturePathEntity.class, 
				"select ppid,sitekey,sitename,domain,abspath,originalpath from picture_path where sitekey=?",
				siteKey);
	}
	/**
	 * 根据sitekey 获取图片尺寸信息
	 * @param siteKey
	 * @return
	 */
	public List<PictureSizeEntity> getPictureSizes(String siteKey){
		return QueryHelper.queryList(PictureSizeEntity.class, 
				"select psid,name,sitekey,width,height from picture_size where sitekey=?",
				siteKey);
	}
	
	/**
	 * 获取图片路径
	 * @param guid
	 * @return
	 */
	public String buildPath(String guid){
		if(guid==null || "".equals(guid)){
			throw new RuntimeException("guid不能为空");
		}
		if(guid.length()<9){
			throw new RuntimeException("guid位数不能小于9");
		}
//		Matcher match=Pattern.compile("^([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})([a-z0-9]{2})").matcher(guid);
//		if(!match.find()){
//			throw new RuntimeException("正则匹配失败");
//		}
//		String path=String.format("%s/%s/%s/%s", 
//				match.group(1),
//				match.group(2),
//				match.group(3),
//				match.group(4));
		String path=String.format("%s/%s/%s/%s",
				guid.substring(0, 2),
				guid.substring(2, 4),
				guid.substring(4, 6),
				guid.substring(6, 8)
				);
		return path;
	}
	/**
	 * 根据id 获取图片所存的服务器信息
	 * @param guid
	 * @return
	 */
	public PicturePathEntity buildPicturePath(List<PicturePathEntity> picturePaths, String guid){
		if(guid==null || "".equals(guid)){
			throw new RuntimeException("guid不能为空");
		}
		if(picturePaths==null || picturePaths.size()==0){
			throw new RuntimeException("picturePaths不能为空");
		}
		int size=picturePaths.size();
		int index=Integer.parseInt(guid.substring(0, 2), 16)%size ;
		return picturePaths.get(index);
	}
	
	/**
	 * 保存图片信息
	 * @param picture
	 * @return 0未影响 1 成功
	 */
	public int savePicture(PictureEntity picture){
		int result=QueryHelper.update(
				"INSERT INTO picture (guid,sitekey,suffix,width,height,size,userid,username,clientip,createtime,md5,isthum,iscrop,iswatermark,isautowidth) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", 
				picture.getGuid(),
				picture.getSiteKey(),
				picture.getSuffix(),
				picture.getWidth(),
				picture.getHeight(),
				picture.getSize(),
				picture.getUserId(),
				picture.getUserName(),
				picture.getClientIp(),
				System.currentTimeMillis()/1000,
				picture.getMd5(),
				picture.getIsthum(),
				picture.getIscrop(),
				picture.getIswatermark(),
				picture.getIsautowidth()
				);
		return result;
	}
	
	/**
	 * 生成图片url
	 * @param lstPicturePath
	 * @param picture
	 * @param width
	 * @param height
	 * @return
	 */
	public String buildImageUrl(List<PicturePathEntity> lstPicturePath,PictureEntity picture,int width,int height){
		PicturePathEntity currentPicturePath= this.buildPicturePath(lstPicturePath, picture.getGuid());
		String midPath= this.buildPath(picture.getGuid());
		if(width==0 && height==0){
			String urlPath=String.format("%s/%s/%s.%s", 
					currentPicturePath.getDomain(),
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
					
			return urlPath;	
		}
		String sizeUrlPath=String.format("%s/%s/%s_%dx%d.%s", 
				currentPicturePath.getDomain(),
				midPath,
				picture.getGuid(),
				width,
				height,
				picture.getSuffix()
				);
		return sizeUrlPath;
	}
	
	public void postPictureToUrl(String url,String filePath,byte[] data,String guid) throws IOException{
		CloseableHttpClient httpClient=HttpClients.createDefault();
		try {
			if(url.indexOf("?")==-1){
				url=String.format("%s?path=%s&guid=%s", url,URLEncoder.encode(filePath,"utf-8"),guid);
			}else{
				url=String.format("%s&path=%s&guid=%s", url,URLEncoder.encode(filePath,"utf-8"),guid);
			}
			HttpPost httppost=new HttpPost(url);
			httppost.setEntity(new ByteArrayEntity(data,ContentType.DEFAULT_BINARY));
			HttpResponse response= httpClient.execute(httppost);
			HttpEntity entity =response.getEntity();
			if(entity!=null){
				String result= EntityUtils.toString(entity);
			}
		}finally{
				httpClient.close();
		}
	}
	
	/**
	 * 保存到绝对文件中
	 * @param fileAbsPath
	 * @param data
	 */
	private void saveToFileSystem(String fileAbsPath,byte[] data){
		String filePath=fileAbsPath.substring(0,fileAbsPath.lastIndexOf("/"));
		File dir=new File(filePath);
		if(!dir.exists()){
			dir.mkdirs();	
		}
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File(fileAbsPath));
			fos.write(data);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			try {
				fos.close();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}	
		}
	}
	/**
	 * 根据配置获取当前普通是否限制宽800的byte[]
	 * @param picture
	 * @return
	 */
	private byte[] buildAutoWeightByte(PictureEntity picture){
		if(picture==null){
			throw new RuntimeException("picture 不能为空！");
		}
		Builder<? extends InputStream> builder= Thumbnails.of(new ByteArrayInputStream(picture.getBinaryData()));
		if(picture.getIsautowidth()==1){
			//宽度为800px
			builder=builder.size(800, picture.getHeight());
			ByteArrayOutputStream baos=new ByteArrayOutputStream();
			try {
				builder.toOutputStream(baos);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			return baos.toByteArray();
		}
		
		return picture.getBinaryData();
	}
	/**
	 * 保存图片
	 * @param lstPicturePath
	 * @param picture
	 * @throws IOException 
	 */
	public void savePictureFile(List<PicturePathEntity> lstPicturePath,PictureEntity picture) throws IOException{
		PicturePathEntity currentPicturePath= this.buildPicturePath(lstPicturePath, picture.getGuid());
		String midPath= this.buildPath(picture.getGuid());
		String originalpath=currentPicturePath.getOriginalpath();
		String absPath=currentPicturePath.getAbspath();
		if(CommonUtils.isNullOrEmpty(originalpath)){
			originalpath=absPath;
		}
		//保存原图
		if(originalpath.startsWith("http://")){
			String filePath=String.format("/%s/original/%s.%s", 
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			this.postPictureToUrl(absPath, filePath, picture.getBinaryData(),picture.getGuid());
		}else {
			String fileAbsPath=String.format("%s/%s/original/%s.%s", 
					absPath,
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			this.saveToFileSystem(fileAbsPath,picture.getBinaryData());
		}
		
		//保存自动生成的
		byte[] targetBytes=this.buildAutoWeightByte(picture);
		if(absPath.startsWith("http://")){
			String filePath=String.format("/%s/%s.%s", 
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			this.postPictureToUrl(absPath, filePath, targetBytes,picture.getGuid());
		}else {
			String fileAbsPath=String.format("%s/%s/%s.%s", 
					absPath,
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			this.saveToFileSystem(fileAbsPath,targetBytes);
		}
		
	}
	/**
	 * 获取图片字节数组
	 * 休息1秒重复3次
	 * @param url
	 * @return
	 */
	public byte[] getHttpPictureData(String url,String referer){
		byte[] dataByte=null;
		int reTryCount=3;
		
		for (int i = 0; i < reTryCount; i++) {
			CloseableHttpClient httpClient=HttpClients.createDefault();
			try {
				
				HttpGet httpget = new HttpGet(url);
				httpget.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
				httpget.addHeader("Referer", referer);
				HttpResponse response= httpClient.execute(httpget);
				HttpEntity entity =response.getEntity();
				if(entity!=null){
					dataByte= EntityUtils.toByteArray(entity);
					break;
				}
			} catch (Exception e) {
				if(i==reTryCount-1){
					throw new RuntimeException(e);
				}
				try {
					Thread.sleep(1000*1);
				} catch (InterruptedException e1) {}
			}finally{
				try {
					httpClient.close();
				} catch (IOException e) {}
			}
		}
		return dataByte;
	}
	
	
	/**
	 * 通过guid获取picture
	 * @param guid
	 * @return
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 */
	public PictureEntity getPictureByGuid(String guid) throws FileNotFoundException, IOException{
		if(CommonUtils.isNullOrEmpty(guid)){
			return null;
		}
		PictureEntity picture=QueryHelper.queryBean(PictureEntity.class, 
				"select pid,guid,sitekey,suffix,width,height,size,userid,username,clientip,createtime,status,md5,isthum,iscrop,iswatermark,isautowidth from picture where guid=?", 
				guid);
		if(picture!=null){
			this.setPictureBytes(picture);
		}
		return picture;
		
	}
	private void setPictureBytes(PictureEntity picture) throws FileNotFoundException, IOException {
		List<PicturePathEntity> lstPicturePath= this.getPicturePaths(picture.getSiteKey());
		PicturePathEntity currentPicturePath= this.buildPicturePath(lstPicturePath, picture.getGuid());
		String midPath=this.buildPath(picture.getGuid());
		String absPath=currentPicturePath.getAbspath();
		byte[] btData=null;
		if(absPath.startsWith("http://")){
			String filePath=String.format("/%s/%s.%s", 
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			CloseableHttpClient httpClient=HttpClients.createDefault();
			if(absPath.indexOf("?")==-1){
				absPath=String.format("%s?path=%s", absPath,URLEncoder.encode(filePath,"utf-8"));
			}else{
				absPath=String.format("%s&path=%s", absPath,URLEncoder.encode(filePath,"utf-8"));
			}
			HttpGet httpget=new HttpGet(absPath);
			HttpResponse response= httpClient.execute(httpget);
			HttpEntity entity =response.getEntity();
			if(entity!=null){
				btData= EntityUtils.toByteArray(entity);
			}
		}else{
			String pictureAbsPath=String.format("%s/%s/%s.%s", 
					currentPicturePath.getAbspath(),
					midPath,
					picture.getGuid(),
					picture.getSuffix()
					);
			
			btData=IOUtils.readByteArray(new FileInputStream(new File(pictureAbsPath)));
		}
		picture.setBinaryData(btData);
	}
	/**
	 * 根据md5和sitekey获取数据
	 * @param md5
	 * @param siteKey
	 * @return
	 */
	public PictureEntity getPictureByMd5(String md5,String siteKey){
		if(CommonUtils.isNullOrEmpty(md5) ||
			CommonUtils.isNullOrEmpty(siteKey)){
			return null;
		}
		return QueryHelper.queryBean(PictureEntity.class, 
				"select pid,guid,sitekey,suffix,width,height,size,userid,username,clientip,createtime,status,md5,isthum,iscrop,iswatermark,isautowidth from picture where md5=? and sitekey=? limit 1", 
				 md5,siteKey);
	}
	/**
	 * 通过md5判断是否存在
	 * @param md5
	 * @return
	 */
	public boolean isExistsPictureByMd5(String md5,String siteKey){
		if(CommonUtils.isNullOrEmpty(md5)){
			throw new PictureException("md5不能为空");
		}
		int result=Integer.parseInt(String.valueOf(QueryHelper.queryScalar("SELECT count(1) as cnt from picture where md5=? and sitekey=?", md5,siteKey)));
		return result>0;
	}
	
	
}
